package com.roger.cmdkit.cases;

import com.roger.cmdkit.base.CmdBase;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.Key;
import java.util.Random;

import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

@SuppressWarnings("ResultOfMethodCallIgnored")
public class FileEnDecrypt implements CmdBase {
    @Override
    public void cmdS(String[] args) {
        try{
            String pathE = System.getProperty("user.dir")+"\\EncryptFile\\";
            String pathD = System.getProperty("user.dir")+"\\DecryptFile\\";
            String fileName = args[1].split("\\\\")[args[1].split("\\\\").length-1];
            if(args[0].equals("-E")){
                try{
                    File f = new File(pathE);
                    if(!f.exists()) f.mkdirs();
                    encryptFile(args[1],pathE+fileName);
                }catch (Throwable e){
                    System.out.println("wtk.exe: -E requires a right file path");
                }
            }else{
                try{
                    File f = new File(pathD);
                    if(!f.exists()) f.mkdirs();
                    decryptedFile(args[1],pathD+fileName);
                }catch (Throwable e){
                    System.out.println("wtk.exe: -D requires a right file path");
                }
            }
        }catch (Throwable e){
            System.out.println("wtk.exe: some mistakes happened");
        }
    }

    private void encryptFile(String fileName,String encryptedFileName){
        try {
            FileInputStream fis = new FileInputStream(fileName);
            FileOutputStream fos = new FileOutputStream(encryptedFileName);
            KeyGenerator keyGenerator=KeyGenerator.getInstance("AES");
            keyGenerator.init(128);
            Key key=keyGenerator.generateKey();
            byte[] keyValue=key.getEncoded();
            fos.write(keyValue);
            SecretKeySpec encryptKey= new SecretKeySpec(keyValue,"AES");
            byte[] ivValue=new byte[16];
            Random random = new Random(System.currentTimeMillis());
            random.nextBytes(ivValue);
            IvParameterSpec iv = new IvParameterSpec(ivValue);
            fos.write("EncryptedByAES".getBytes());
            fos.write(ivValue);
            Cipher cipher = Cipher.getInstance("AES/CFB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, encryptKey,iv);
            CipherInputStream cis=new CipherInputStream(fis, cipher);
            byte[] buffer=new byte[1024];
            int n=0;
            while((n=cis.read(buffer))!=-1){
                fos.write(buffer,0,n);
            }
            System.out.println("encrypt success");
            cis.close();
            fos.close();
            fis.close();
        } catch (Throwable e) {
            System.out.println("encrypt file fail,check your file path pls");
        }

    }

    private  void decryptedFile(String encryptedFileName, String decryptedFileName){
        try {
            FileInputStream fis = new FileInputStream(encryptedFileName);
            FileOutputStream fos = new FileOutputStream(decryptedFileName);
            byte[] fileId=new byte[14];
            byte[] keyValue=new byte[16];
            fis.read(keyValue);
            fis.read(fileId);
            if(new String(fileId).equals("EncryptedByAES")){
                SecretKeySpec key= new SecretKeySpec(keyValue,"AES");
                byte[] ivValue= new byte[16];
                fis.read(ivValue);
                IvParameterSpec iv= new IvParameterSpec(ivValue);
                Cipher cipher = Cipher.getInstance("AES/CFB/PKCS5Padding");
                cipher.init(Cipher.DECRYPT_MODE, key,iv);
                CipherInputStream cis= new CipherInputStream(fis, cipher);
                byte[] buffer=new byte[1024];
                int n=0;
                while((n=cis.read(buffer))!=-1){
                    fos.write(buffer,0,n);
                }
                cis.close();
                fos.close();
                fis.close();
                System.out.println("decrypt success");
            }else{
                System.out.println("it is not decrypted by this tool");
            }
        } catch (Throwable e) {
            System.out.println("decrypt file fail,check your file path pls");
        }
    }
}
